package com.liuyk.commonlib.manager;

import android.app.ActivityManager;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.widget.ImageView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.airbnb.lottie.LottieAnimationView;
import com.airbnb.lottie.LottieComposition;
import com.airbnb.lottie.LottieOnCompositionLoadedListener;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.DecodeFormat;
import com.bumptech.glide.load.Transformation;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
import com.bumptech.glide.load.resource.bitmap.CircleCrop;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.target.DrawableImageViewTarget;
import com.bumptech.glide.request.target.Target;
import com.bumptech.glide.request.transition.Transition;
import com.liuyk.commonlib.App;
import com.liuyk.commonlib.utility.FileUtils;

import java.io.File;

/**
 * 图片加载
 * 1. 圆形加载
 * 2. 圆角加载
 * 3. 模糊效果
 * 4. listener
 * 5. 下载图片
 * <p>
 * 一般三方框架实现圆形/圆角效果，都是使用者传进去一个Bitmap，框架内部，会生成一个一模一样得Bitmap，然后裁剪，
 * * 实现圆形或者圆角，这个时候内存会翻倍，Glide用的是transformations 在原有得Bitmap上进行变换，节省内存
 * <p>
 * Created by liuyakui on 2020/1/16.
 */
public class ImageLoaderManager {

    public static void loadImage(String url, ImageView target) {
        loadImage(url, target, false, 0, 0, 0, null, null);
    }

    public static void loadImage(String url, ImageView target, ImageLoadingCallBack listener) {
        loadImage(url, target, false, 0, 0, 0, listener, null);
    }

    public static void loadImage(String url, ImageView target, final Transformation<Bitmap>[] transformations) {
        if (transformations == null) {
            //掉这个方法，transformations不可传null
            return;
        }
        loadImage(url, target, false, 0, 0, 0, null, transformations);
    }

    public static void loadImage(String url, ImageView target, final Transformation<Bitmap>[] transformations, int failResId, int loadResId) {
        if (transformations == null) {
            //掉这个方法，transformations不可传null
            return;
        }
        loadImage(url, target, false, 0, failResId, loadResId, null, transformations);
    }

    public static void loadImage(String url, ImageView target, int roundedCorners) {
        loadImage(url, target, roundedCorners, 0, 0);
    }

    public static void loadImage(String url, ImageView target, int roundedCorners, int failResId, int loadResId) {
        loadImage(url, target, roundedCorners, failResId, loadResId, null);
    }

    public static void loadImage(String url, ImageView target, int roundedCorners, int failResId, int loadResId, ImageLoadingCallBack callBack) {
        loadImage(url, target, false, roundedCorners, failResId, loadResId, callBack, null);
    }

    public static void loadImage(String url, ImageView target, boolean isCircle) {
        loadImage(url, target, isCircle, 0, 0);
    }

    public static void loadImage(String url, ImageView target, boolean isCircle, int failResId, int loadResId) {
        loadImage(url, target, isCircle, failResId, loadResId, null);
    }

    public static void loadImage(String url, ImageView target, boolean isCircle, int failResId, int loadResId, ImageLoadingCallBack callBack) {
        loadImage(url, target, isCircle, 0, failResId, loadResId, callBack, null);
    }

    /**
     * 图片加载
     *
     * @param url            图片URL
     * @param target         ImageView
     * @param isCircle       是否圆形图
     * @param roundedCorners 是否圆角 注意：圆形和圆角不要同时使用
     * @param failResId      加载失败图
     * @param loadResId      正在加载图
     * @param callBack       回调
     */
    public static void loadImage(final String url, ImageView target, boolean isCircle, int roundedCorners, int failResId, int loadResId, final ImageLoadingCallBack callBack, final Transformation<Bitmap>[] transformations) {
        if (TextUtils.isEmpty(url) || target == null || target.getContext() == null) {
            return;
        }
        try {
            Glide.with(target.getContext()).load(url).apply(getOptions(failResId, loadResId, false, isCircle, roundedCorners, transformations)).into(new DrawableImageViewTarget(target) {

                public void onResourceReady(@NonNull Drawable resource, Transition<? super Drawable> transition) {
                    super.onResourceReady(resource, transition);
                    if (callBack != null) {
                        callBack.onLoadingComplete(((BitmapDrawable) resource).getBitmap());
                    }
                }

                public void onLoadFailed(Drawable errorDrawable) {
                    super.onLoadFailed(errorDrawable);
                    if (callBack != null) {
                        callBack.onLoadingFailed(url);
                    }
                }

                public void onLoadStarted(Drawable placeholder) {
                    super.onLoadStarted(placeholder);
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static RequestOptions getOptions(int errorRes, int loadingRes) {
        return getOptions(errorRes, loadingRes, false, false, 0, null);
    }

    private static RequestOptions getOptions(int errorRes, int loadingRes, boolean source, boolean isCircle, int roundedCorners, Transformation<Bitmap>[] transformations) {
        //AppGlideModule和RequestOptions和新型缓存配置 都是4.x出现的

        //DiskCacheStrategy.NONE： 表示不缓存任何内容。
        //DiskCacheStrategy.DATA： 表示只缓存原始图片。
        //DiskCacheStrategy.RESOURCE： 表示只缓存转换过后的图片。
        //DiskCacheStrategy.ALL ： 表示既缓存原始图片，也缓存转换过后的图片。
        //DiskCacheStrategy.AUTOMATIC： 表示让Glide根据图片资源智能地选择使用哪一种缓存策略（默认选项）。
        DiskCacheStrategy strategy = DiskCacheStrategy.RESOURCE;
        if (source) {
            strategy = DiskCacheStrategy.DATA;
        }

        RequestOptions requestOptions = new RequestOptions().placeholder(loadingRes).error(errorRes).skipMemoryCache(false).format(getDecodeFormat()).diskCacheStrategy(strategy);

        if (transformations != null) {
            //表示自定义了transformations
            requestOptions.transform(transformations);
            return requestOptions;
        }
        if (isCircle) {
            requestOptions.transform(new CircleCrop());
        }
        if (roundedCorners != 0) {
            requestOptions.transform(new CenterCrop(), new RoundedCorners(roundedCorners));
        }
        return requestOptions;
    }

    private static DecodeFormat getDecodeFormat() {
        DecodeFormat decodeFormat = DecodeFormat.PREFER_RGB_565;
        boolean lowMemory = false;//留个开关，观察内存，切换图片采样率
        try {
            ActivityManager manager = (ActivityManager) App.context.getSystemService(Context.ACTIVITY_SERVICE);
            if (manager != null) {
                ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
                manager.getMemoryInfo(memoryInfo);
                lowMemory = memoryInfo.lowMemory;
            }
            if (!lowMemory) {
                decodeFormat = DecodeFormat.PREFER_ARGB_8888;
            }
        } catch (Exception var2) {
            var2.printStackTrace();
        }
        return decodeFormat;
    }

    public static void loadLottie(final String url, final LottieAnimationView view) {
        loadLottie(url, view, null);
    }

    /**
     * 从远端加载gif，返回需是json格式
     *
     * @param url      url
     * @param view     view
     * @param callBack 回调
     */
    public static void loadLottie(final String url, final LottieAnimationView view, final LottieCallBack callBack) {
        if (view != null) {
//            view.setImageResource(options.getPlaceholderId());//设置占位
            try {
                // 开启硬件加速
                view.setAnimationFromUrl(url);
                view.addLottieOnCompositionLoadedListener(new LottieOnCompositionLoadedListener() {
                    public void onCompositionLoaded(LottieComposition lottieComposition) {
                        if (lottieComposition != null) {
                            view.setComposition(lottieComposition);
                            view.playAnimation();
                            if (callBack != null) {
                                callBack.onLoadingComplete(url);
                            }
                        } else {
                            if (callBack != null) {
                                callBack.onLoadingFailed(url);
                            }
                        }
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static void loadLottieFromAssetName(final String assetName, final LottieAnimationView view) {
        if (view != null) {
            // 开启硬件加速
            view.setAnimation(assetName);
            view.addLottieOnCompositionLoadedListener(new LottieOnCompositionLoadedListener() {
                public void onCompositionLoaded(LottieComposition lottieComposition) {
                    if (lottieComposition != null) {
                        view.setComposition(lottieComposition);
                        view.playAnimation();
                    }
                }
            });
        }
    }

    public static void loadImage(Context context, String path, ImageLoadingCallBack callBack) {
        loadImage(context, null, path, -2147483648, -2147483648, callBack);
    }

    /**
     * 指定宽高加载图片
     *
     * @param context  application上下文
     * @param iv       ImageView 可以为null, 从回调里面自行处理
     * @param path     图片Url
     * @param width    指定图片的宽
     * @param height   指定图片的高
     * @param callBack 回调
     */
    public static void loadImage(Context context, final ImageView iv, final String path, int width, int height, final ImageLoadingCallBack callBack) {
        RequestOptions options = new RequestOptions();
        options.diskCacheStrategy(DiskCacheStrategy.DATA);
        Glide.with(context).load(path).listener(new RequestListener<Drawable>() {
            public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
                if (callBack != null) {
                    callBack.onLoadingFailed(path);
                }
                return false;
            }

            public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
                try {
                    final Bitmap bitmap = ((BitmapDrawable) resource).getBitmap();
                    if (iv != null) {
                        iv.setImageBitmap(bitmap);
                    }
                    if (callBack != null) {
                        callBack.onLoadingComplete(bitmap);
                    }
                } catch (Exception var7) {
                    callBack.onLoadingFailed(path);
                }
                return false;
            }
        }).apply(options).preload(width, height);
    }

    public static void downloadImage(Context context, String path, DownloadCallBack callBack) {
        downloadImage(context, path, -2147483648, -2147483648, callBack);
    }

    public static void downloadImage(final Context context, final String path, int width, int height, final DownloadCallBack callBack) {
        Glide.with(context).load(path).listener(new RequestListener<Drawable>() {
            public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
                if (callBack != null) {
                    callBack.downloadFail(path);
                }
                return false;
            }

            public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
                try {
                    Bitmap bitmap = ((BitmapDrawable) resource).getBitmap();
                    File file = FileUtils.bitmapToFile(context, bitmap);
                    if (file != null) {
                        if (callBack != null) {
                            callBack.downloadSuccess(path, file);
                        }
                    } else {
                        if (callBack != null) {
                            callBack.downloadFail(path);
                        }
                    }

                } catch (Exception var7) {
                    if (callBack != null) {
                        callBack.downloadFail(path);
                    }
                }
                return false;
            }
        }).preload(width, height);
    }

    /**
     * 加载gif，这个暂时用Glide，下个版本在切换
     *
     * @param iv  target
     * @param url url
     */
    public static void loadGif(ImageView iv, String url) {
        Glide.with(iv.getContext()).asGif().load(url).into(iv);
    }

    //官方整理内存推荐写法
    public static void clearDiskMemory(Context context) {
        try {
            Glide.get(context).clearDiskCache();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void trimMemory(Context context, int level) {
        Glide.get(context).trimMemory(level);
    }

    public interface ImageLoadingCallBack {

        void onLoadingFailed(String path);

        void onLoadingComplete(Bitmap bitmap);
    }

    public interface LottieCallBack {
        void onLoadingFailed(String url);

        void onLoadingComplete(String url);
    }

    public interface DownloadCallBack {
        void downloadFail(String url);

        void downloadSuccess(String url, File file);
    }
}
